package com.symaster.common.connect.tcp;

import com.alibaba.fastjson.JSONObject;
import com.symaster.common.connect.util.ClientIO;
import com.symaster.common.thread.WatchThread;
import com.symaster.common.util.IOUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.UUID;

/**
 * @author yinmiao
 * @version 2022-05-03 11:33
 */
public class TcpElementR extends WatchThread implements Closeable {

    private final ServerSocket serverSocket;
    private Socket socket;
    private MessageHandler messageHandler;
    private ConnectClosedListener connectClosedListener;
    private ConnectSuccessListener connectSuccessListener;
    private InputStream is;
    private OutputStream os;

    public TcpElementR(int port) throws IOException {
        super(0, "symaster-tcp-element-r-" + UUID.randomUUID());
        serverSocket = new ServerSocket(port);
        serverSocket.setReceiveBufferSize(102400);
        serverSocket.getReceiveBufferSize();
        init();
    }

    public boolean init() {
        new Thread(() -> {
            try {
                socket = serverSocket.accept();
                socket.setReceiveBufferSize(102400);
                is = socket.getInputStream();
                os = socket.getOutputStream();
                if (connectSuccessListener != null) connectSuccessListener.handler();
                start();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }).start();
        return true;
    }

    public void setMessageHandler(MessageHandler messageHandler) {
        this.messageHandler = messageHandler;
    }

    public void setConnectClosedListener(ConnectClosedListener connectClosedListener) {
        this.connectClosedListener = connectClosedListener;
    }

    public void setConnectSuccessListener(ConnectSuccessListener connectSuccessListener) {
        this.connectSuccessListener = connectSuccessListener;
    }

    @Override
    protected void execute() throws Exception {

        try {
            String message = ClientIO.getString(socket.getInputStream());
            JSONObject jsonObject = JSONObject.parseObject(message);

            String resultStr = messageHandler != null ? messageHandler.handler(jsonObject.getString("message")) : null;
            if ("notResult".equals(jsonObject.getString("type"))) return;

            if (StringUtils.isNotEmpty(resultStr)) {
                ClientIO.writeStr(socket.getOutputStream(), resultStr);
            } else {
                ClientIO.writeStr(socket.getOutputStream(), "$$$NULL$$$");
            }

        } catch (SocketException e) {
            if (connectClosedListener != null) connectClosedListener.handler();
            close();
        }
    }

    @Override
    protected void startEvent() {
    }

    @Override
    protected void stopEvent(int o) {
    }

    @Override
    public void close() {
        IOUtil.close(socket, serverSocket, is, os);
        stop();
    }

    public interface MessageHandler {
        String handler(String message);
    }

    public interface ConnectClosedListener {
        void handler();
    }

    public interface ConnectSuccessListener {
        void handler();
    }
}
